//
// Created by vivi on 09/02/2018.
//

#pragma once
#include <Eigen/Eigen>
#include "core/precompiled/precompiled.h"

namespace HairEngine {
	/*
	 * The data that hair engine needs for simulate for one simulation step
	 */
	struct HairEngineSimulationData {
		Eigen::Affine3f transform; //The rigid transform for driven the movement of the hair root
		Eigen::Affine3f previousTransform; //The previous rigid transform for last simulation
		float t; //The time between the last simulation frame and current simulation frame

		/*
		 * Initialize a HairEngineSimulationData used for initialization, which represents the simulation information in the
		 * rest state. That is, the frameNumber is 0, the transform and the previousTransform is equal to
		 * the rest transform. And t is initialized to -1.0f (which is invalid in actual simulation);
		 */
		explicit HairEngineSimulationData(const Eigen::Affine3f & restTransform);

		//Direct initialization
		HairEngineSimulationData(const Eigen::Affine3f & transform_,
		                         const Eigen::Affine3f & previousTransform_,
		                         float t_);

		/*
		 * Update the HairEngineSimulationData, transform_ specifies the new affine transform for the rigid body,
		 * t_ specifies the new time step
		 */
		void update(const Eigen::Affine3f & transform_, float t_);

		/*
		 * To tell whether current HairEngineSimulationData is used for initial or it is for real simulation.
		 * We check the time t, if it is smaller or equal to 0, that indicates that it is used for initialization,
		 * otherwise it is used for simulation;
		 */
		inline bool isInital() const;
	};

	/*
	 * Base class for Hair Engine, only one interface should be implemented
	 */
	class HairEngine {
	Public:
		virtual void simulate(const HairEngineSimulationData& data) = 0;

		virtual ~HairEngine() = default;
	};
}